package pnu.ssm.sbchild;

import java.io.IOException;
import java.util.List;

import pnu.ssm.appinfo.AppInfo;
import pnu.ssm.appinfo.AppListHelper;
import pnu.ssm.broadcast.GcmIntentService;
import pnu.ssm.http.HttpConnector;
import pnu.ssm.key.Key;
import pnu.ssm.question.Question;
import pnu.ssm.question.QuestionManager;
import pnu.ssm.service.AppProtectService;
import pnu.ssm.service.ResurrectionService;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;

public class MainActivity extends Activity implements Button.OnClickListener, View.OnTouchListener {

	public static final String TAG = "MainActivity";
	private final boolean Debug = true;
	private final boolean ServiceDebug = true;

	// SharedPreferences 에 저장되는 데이터 목록
	// connect key : "LogonPref"
	// parent_phone_number : 부모 폰 번호 저장됨 (String)
	// parentKey : 부모와 연결되었는지 여부 (Boolean)
	public static boolean MAIN_ACTIVE;
	public static final int UPDATE_APP_LIST = 1;
	public static final int UPDATE_CHINESE_SETTING = 2;

	public static final String EXTRA_MESSAGE = "message";
	public static final String PROPERTY_REG_ID = "registration_id";
	private static final String PROPERTY_APP_VERSION = "appVersion";
	private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
	private String SENDER_ID = "770124100954";

	private GoogleCloudMessaging gcm;
	private SharedPreferences pref;
	private SharedPreferences.Editor editor;
	private Context context;
	private String regid;
	private HttpConnector httpConnector;
	private ProgressDialog progressDialog;
	private AppListHelper appListHelper = AppListHelper.getInstance(); 

	private boolean isStartService = false;
	private static boolean didYouLoadForbidden = false;
	private ImageView iv_present;

	private QuestionManager mQuestionManager;

	//	TextView tv_curr_obtain_time;
	//	TextView tv_curr_extra_time;

	// msgHandler는 MainActivity의 핸들러다. 이 핸들러를 Service에게 넘겨줘서 Service가 이 핸들러에게 메시지를 보내줄수 있게 해야한다. 
	private Handler mainHandler = new Handler(){
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case UPDATE_APP_LIST:
				Log.e(TAG, "Forbidden app list is updated");
				break;
			case UPDATE_CHINESE_SETTING:
				Bundle bundle = msg.getData();
				String extra_time = bundle.getString(Key.extra_time);
				String obtain_time = bundle.getString(Key.obtain_time);
				//				tv_curr_extra_time.setText(extra_time+"분");
				//				tv_curr_obtain_time.setText(obtain_time+"분");
				Log.d(TAG,"Chinese setting is updated");
				break;
			default:
				Log.e(TAG, "incoming handelr received message.");
				break;
			}
		};
	};

	//msgHandler를 감싸기 위한 Messenger
	private Messenger msgSender = new Messenger(mainHandler);

	// mService는 Service의 핸들러다. 이 핸들러를 통해 Service에게 message를 보내게 된다.
	private Messenger mService = null; 
	private ServiceConnection mConnection = new ServiceConnection() {
		@Override
		public void onServiceConnected(ComponentName className, IBinder service) {
			mService = new Messenger(service);

			// Service에게 Activity의 핸들러는 넘겨준다.
			Message msg = Message.obtain(null,GcmIntentService.ADD_RESPONSE_HANDLER);
			msg.replyTo = msgSender;
			try { mService.send(msg); } 
			catch (RemoteException e) {
				e.printStackTrace();
			}
		}
		@Override
		public void onServiceDisconnected(ComponentName className) {
			mService = null;
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);

		buildBackgroundService();
		buildUI();	
		buildConnector();
		setUpGCMServer();
		setUpQuestionManager();
		
		//bind activity with gcm service.
		bindService(new Intent(MainActivity.this,GcmIntentService.class), mConnection, Context.BIND_AUTO_CREATE);

		loadForbiddenList();
	}

	@Override
	protected void onResume() { 
		super.onResume();
		checkPlayServices();
		MAIN_ACTIVE = true;
	}

	@Override
	protected void onPause() {
		super.onPause();
		MAIN_ACTIVE = false;
	}

	private void buildBackgroundService(){
		if(!isStartService && ServiceDebug){
			Intent appProtectIntent = new Intent(MainActivity.this, AppProtectService.class);
			startService(appProtectIntent);
			
			Intent recursionIntent = new Intent(MainActivity.this, ResurrectionService.class);
			startService(recursionIntent);
			
			isStartService = true;
		}
	}

	private void buildUI(){
		context = getApplicationContext();
		pref = getSharedPreferences(Key.prefKey, MODE_PRIVATE);
		editor = pref.edit();

		iv_present = (ImageView) findViewById(R.id.iv_present);
		iv_present.setOnClickListener(this);

		//		tv_curr_obtain_time = (TextView) findViewById(R.id.tv_curr_obtain_time);
		//		tv_curr_extra_time = (TextView) findViewById(R.id.tv_curr_extra_time);

		progressDialog = new ProgressDialog(this);
		progressDialog.setTitle("Mom's Locker");
		progressDialog.setIndeterminate(true);
		progressDialog.setCancelable(true);
		progressDialog.setMessage("Please wait while loading...");
	}	

	private void setUpGCMServer(){
		if (checkPlayServices()) {
			Log.i(TAG,"has api of play services");
			gcm = GoogleCloudMessaging.getInstance(this);
			regid = getRegistrationId(context);
			if (regid == "" || regid == null) 
				registerInBackground();
			Log.e(TAG, "regID : "+regid);
		}else{
			Log.e(TAG, "No valid Google Play Services APK found.");
		}	
	}
	
	private void setUpQuestionManager() {
		mQuestionManager = new QuestionManager(getApplicationContext());
	}

	private void buildConnector(){
		httpConnector = HttpConnector.getInstance();
	}

	private void loadForbiddenList(){
		//한자 정보도 함께 받도록 함
		final String child_num = pref.getString(Key.child_num, "0");
		if(child_num != null && !didYouLoadForbidden){
			new AsyncTask<Void, Void, Void>(){
				@Override
				protected void onPreExecute() {
					super.onPreExecute();
					progressDialog.show();
				};
				@Override
				protected Void doInBackground(Void... arg0) {
					List<AppInfo> appInfoList = httpConnector.getForbiddenAppList(child_num);
					appListHelper.setForbiddenAppList(appInfoList);
					httpConnector.getChineseSetting(child_num, editor); // 한자 환경설정

					String obtain_time = pref.getString(Key.obtain_time, "0");
					String extra_time = pref.getString(Key.extra_time, "0");

					Message msg = Message.obtain();
					msg.what = UPDATE_CHINESE_SETTING;

					Bundle bundle = new Bundle();
					bundle.putString(Key.extra_time, extra_time);
					bundle.putString(Key.obtain_time, obtain_time);
					msg.setData(bundle);

					mainHandler.sendMessage(msg);
					return null;
				}
				@Override
				protected void onPostExecute(Void result) {
					super.onPostExecute(result);
					progressDialog.dismiss();
					didYouLoadForbidden = true;
				};
			}.execute(null,null,null);
		}
	}

	public void startQuestionActivity() {
		Question question = mQuestionManager.requestRandomQuestion();

		Intent intent = new Intent(MainActivity.this, ChoiceActivity.class);
		intent.putExtra(ChoiceActivity.QUESTION, question);

		MainActivity.this.startActivityForResult(intent, ChoiceActivity.CHOICE_ACTIVITY);
	}

	/*
	 * implements Button.OnClickListener
	 */

	@Override
	public void onClick(View v) {
		int id = v.getId();
		switch (id) {
		case R.id.iv_present:
			Log.d(TAG, "locker clicked");
			
			//Intent intent = new Intent(MainActivity.this, TestActivity.class);
			//startActivity(intent);
			
			startQuestionActivity();

			break;
		default:
			break;
		}
	}

	/*
	 * implements View.OnTouchListener
	 */

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		int id = v.getId();
		switch (id) {
		case R.id.iv_present:
			Log.d(TAG, "ll_draw");
			//Intent intent = new Intent(MainActivity.thisc, ChineseActivity.class);
			//startActivity(intent);
			break;
		default:
			break;
		}
		return false;
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		if(requestCode == ChoiceActivity.CHOICE_ACTIVITY){
			if(resultCode == ChoiceActivity.SUCCESS){
				//Toast.makeText(getBaseContext(), "correct", Toast.LENGTH_SHORT).show();

				pref = getPreferences(MODE_PRIVATE);
				editor = pref.edit();

				String child_num = pref.getString(Key.child_num, "0");
				String extra_time = pref.getString(Key.extra_time, "5"); // 한문제당 얻는 시간 (고정)
				String obtain_time = pref.getString(Key.obtain_time, "0");

				int obtain_time_int = Integer.parseInt(extra_time) + Integer.parseInt(obtain_time);
				editor.putString(Key.obtain_time, String.valueOf(obtain_time_int));
				editor.commit();

				/*Thread chineseThread = new Thread(new ChineseTask(child_num, obtain_time));
				chineseThread.start(); //sending..*/	
				
				AppProtectService.enabled = false;
				
				showDialog(true, "1");
			}else if (resultCode == ChoiceActivity.FAIL) {
				//Toast.makeText(getBaseContext(), "wrong", Toast.LENGTH_SHORT).show();

				AppProtectService.enabled = true;
				
				showDialog(false, "");
			} else {
				
			}
		}
		Log.i(TAG, "here is correct!!!!!");
	}
	
	class ChineseTask implements Runnable{
		String child_num;
		String obtain_time;
		
		public ChineseTask(String child_num, String obtain_time) {
			this.child_num = child_num;
			this.obtain_time = obtain_time;
		}
		@Override
		public void run() {
			httpConnector.sendChineseState(child_num, obtain_time);
		}
	}
	
	private void showDialog(final boolean success, String extra_time){
		String msg = "";
		if(success){
			msg = extra_time + "분을 획득했습니다.";
		}else{
			msg = "틀렸네요. 다음 기회에...";
		}
		
	    AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
	    alt_bld.setMessage(msg)
	    .setCancelable(true)
	    .setPositiveButton("확인",new DialogInterface.OnClickListener() {
	        @Override
			public void onClick(DialogInterface dialog, int id) {
	        	if (success) {
	        		finish();
	        	}
	        	else {
	        		startQuestionActivity();
	        	}
	        		
	        }});
	    AlertDialog alert = alt_bld.create();
	    alert.setTitle("Mom's Locker");
	    alert.setIcon(R.drawable.ic_launcher);
	    alert.show();
	}






	/**
	 * Check the device to make sure it has the Google Play Services APK. If
	 * it doesn't, display a dialog that allows users to download the APK from
	 * the Google Play Store or enable it in the device's system settings.
	 */

	private boolean checkPlayServices() {
		if(Debug) Log.i(TAG,"checkPlayServices()");
		int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
		if (resultCode != ConnectionResult.SUCCESS) {
			if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
				GooglePlayServicesUtil.getErrorDialog(resultCode, this,
						PLAY_SERVICES_RESOLUTION_REQUEST).show();
			} else {
				Log.i(TAG, "This device is not supported.");
				finish();
			}
			return false;
		}
		return true;
	}

	/**
	 * Gets the current registration ID for application on GCM service.
	 * <p>
	 * If result is empty, the app needs to register.
	 *
	 * @return registration ID, or empty string if there is no existing
	 *         registration ID.
	 */
	private String getRegistrationId(Context context) {
		if(Debug) Log.i(TAG,"getRegistrationId()");
		final SharedPreferences prefs = getGCMPreferences(context);
		String registrationId = prefs.getString(PROPERTY_REG_ID, "");
		if (registrationId == "" || registrationId == null) {
			Log.i(TAG, "Registration not found.");
			return "";
		}
		// Check if app was updated; if so, it must clear the registration ID
		// since the existing regID is not guaranteed to work with the new
		// app version.
		int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
		int currentVersion = getAppVersion(context);
		if (registeredVersion != currentVersion) {
			Log.i(TAG, "App version changed.");
			return "";
		}
		return registrationId;
	}

	/**
	 * @return Application's {@code SharedPreferences}.
	 */
	private SharedPreferences getGCMPreferences(Context context) {
		if(Debug) Log.i(TAG,"getGCMPreferences()");
		// This sample app persists the registration ID in shared preferences, but
		// how you store the regID in your app is up to you.
		return getSharedPreferences(MainActivity.class.getSimpleName(), Context.MODE_PRIVATE);
	}

	/**
	 * @return Application's version code from the {@code PackageManager}.
	 */
	private static int getAppVersion(Context context) {
		Log.i(TAG,"getAppVersion()");
		try {
			PackageInfo packageInfo = context.getPackageManager()
					.getPackageInfo(context.getPackageName(), 0);
			return packageInfo.versionCode;
		} catch (NameNotFoundException e) {
			// should never happen
			throw new RuntimeException("Could not get package name: " + e);
		}
	}

	/**
	 * Registers the application with GCM servers asynchronously.
	 * Stores the registration ID and app versionCode in the application's
	 * shared preferences.
	 */
	private void registerInBackground(){
		new AsyncTask<String, Void, String>(){
			@Override
			protected String doInBackground(String... params) {
				String msg = "";
				try {
					if(Debug) Log.i(TAG,"registerInBackground()");
					if (gcm == null)  gcm = GoogleCloudMessaging.getInstance(context);

					regid = gcm.register(SENDER_ID);
					msg = "Device registered, registration ID=" + regid;

					// You should send the registration ID to your server over HTTP,
					// so it can use GCM/HTTP or CCS to send messages to your app.
					// The request to your server should be authenticated if your app
					// is using accounts.
					sendRegistrationIdToBackend();

					// For this demo: we don't need to send it because the device
					// will send upstream messages to a server that echo back the
					// message using the 'from' address in the message.

					// Persist the regID - no need to register again.
					storeRegistrationId(context, regid);
				} catch (IOException ex) {
					msg = "Error :" + ex.getMessage();
					// If there is an error, don't just keep trying to register.
					// Require the user to click a button again, or perform
					// exponential back-off.
				}
				return msg;
			}

			@Override
			protected void onPostExecute(String result) {
				// 3rd Party Server에 ID 등록 후에 작동할 코드. 
			}

			private void sendRegistrationIdToBackend() {
				// Your implementation here.
				if(Debug) Log.e(TAG,"sendRegistrationIdToBackend()");
				//				String phoneNumber = pref.getString(Key.parent_phone_num, "nothing");
				String child_num = pref.getString(Key.child_num, "nothing");
				if(child_num.equals("nothing")){
					Log.e(TAG, "couldn't get child number");
				}else{
					httpConnector.sendRegistrationID(child_num, regid);
				}
			}
		}.execute(null,null,null);
	}

	private void storeRegistrationId(Context context, String regId) {
		if(Debug) Log.i(TAG,"storeRegistrationId()");
		final SharedPreferences prefs = getGCMPreferences(context);
		int appVersion = getAppVersion(context);
		Log.i(TAG, "Saving regId on app version " + appVersion);
		SharedPreferences.Editor editor = prefs.edit();
		editor.putString(PROPERTY_REG_ID, regId);
		editor.putInt(PROPERTY_APP_VERSION, appVersion);
		editor.commit();
	}

}








